package com.gxc.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author GongXincheng
 * @since 2019-07-30 18:16
 */
@Slf4j
@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.gxc.controller.*.*(..))")
    public void pointCut() {}

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object proceed = null;
        try {
            Map<String, Object> map = new HashMap<>();

            // 获取类名
            String className = joinPoint.getTarget().getClass().getName();
            map.put("className", className);

            // 获取方法名称
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            String methodName = method.getName();
            map.put("methodName", methodName);

            // 获取方法参数
            Object[] args = joinPoint.getArgs();
            String[] parameterNames = methodSignature.getParameterNames();
            Map<String, Object> paramsMap = new HashMap<>();
            for (int i = 0; i < parameterNames.length; i++) {
                Object arg = args[i];
                if (arg instanceof ServletRequest
                        || arg instanceof ServletResponse
                        || arg instanceof HttpSession) {
                    continue;
                }
                paramsMap.put(parameterNames[i], arg);
            }
            map.put("params", paramsMap);


            // 获取请求信息
            getHttpRequest(map);

            // 执行方法
            proceed = joinPoint.proceed();

            // 获取结果
            map.put("result", JSON.toJSONString(proceed));

            // 打印日志
            log.info("请求日志 --> {}", JSON.toJSONString(map));
        } catch (Throwable throwable) {
            log.error("接口出现异常！");
            throwable.printStackTrace();
        }
        return proceed;
    }

    private void getHttpRequest(Map<String, Object> map) {
        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        StringBuffer url = request.getRequestURL();
        String requestMethod = request.getMethod();
        String ip = request.getRemoteAddr();
        map.put("url", url.toString());
        map.put("requestMethod", requestMethod);
        map.put("ip", ip);
    }

}
